ജാവാസ്ക്രിപ്റ്റ് അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പർ 'സ്കാൻ', അതിൻ്റെ പ്രവർത്തനം, ഉപയോഗങ്ങൾ, അസിൻക്രണസ് അക്യുമുലേറ്റീവ് പ്രോസസ്സിംഗിനുള്ള പ്രയോജനങ്ങൾ എന്നിവ പര്യവേക്ഷണം ചെയ്യുന്നു.
ജാവാസ്ക്രിപ്റ്റ് അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പർ: സ്കാൻ - അസിങ്ക് അക്യുമുലേറ്റീവ് പ്രോസസ്സിംഗ്
ആധുനിക ജാവാസ്ക്രിപ്റ്റ് ഡെവലപ്മെൻ്റിൻ്റെ ഒരു അടിസ്ഥാന ശിലയാണ് അസിൻക്രണസ് പ്രോഗ്രാമിംഗ്, പ്രത്യേകിച്ച് നെറ്റ്വർക്ക് അഭ്യർത്ഥനകൾ അല്ലെങ്കിൽ ഫയൽ സിസ്റ്റം ഇടപെടലുകൾ പോലുള്ള I/O-ബൗണ്ട് ഓപ്പറേഷനുകൾ കൈകാര്യം ചെയ്യുമ്പോൾ. അസിങ്ക് ഇറ്ററേറ്ററുകൾ, ES2018-ൽ അവതരിപ്പിച്ചത്, അസിൻക്രണസ് ഡാറ്റയുടെ സ്ട്രീമുകൾ കൈകാര്യം ചെയ്യുന്നതിനുള്ള ശക്തമായ ഒരു സംവിധാനം നൽകുന്നു. RxJS പോലുള്ള ലൈബ്രറികളിൽ പലപ്പോഴും കാണുന്നതും സ്റ്റാൻഡലോൺ യൂട്ടിലിറ്റിയായി കൂടുതലായി ലഭ്യമാകുന്നതുമായ `scan` ഹെൽപ്പർ, ഈ അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകൾ പ്രോസസ്സ് ചെയ്യുന്നതിന് കൂടുതൽ സാധ്യതകൾ തുറക്കുന്നു.
അസിങ്ക് ഇറ്ററേറ്ററുകളെ മനസ്സിലാക്കുന്നു
`scan`-ലേക്ക് കടക്കുന്നതിന് മുമ്പ്, അസിങ്ക് ഇറ്ററേറ്ററുകൾ എന്താണെന്ന് നമുക്ക് നോക്കാം. അസിങ്ക് ഇറ്ററേറ്റർ പ്രോട്ടോക്കോളിന് അനുസൃതമായ ഒരു ഒബ്ജക്റ്റാണ് അസിങ്ക് ഇറ്ററേറ്റർ. ഈ പ്രോട്ടോക്കോൾ ഒരു `next()` മെത്തേഡ് നിർവചിക്കുന്നു, അത് രണ്ട് പ്രോപ്പർട്ടികളുള്ള ഒരു ഒബ്ജക്റ്റിലേക്ക് പരിഹരിക്കുന്ന ഒരു പ്രോമിസ് നൽകുന്നു: `value` (ക്രമത്തിലെ അടുത്ത മൂല്യം), `done` (ഇറ്ററേറ്റർ പൂർത്തിയായോ എന്ന് സൂചിപ്പിക്കുന്ന ഒരു ബൂളിയൻ). കാലക്രമേണ എത്തുന്ന ഡാറ്റയുമായോ, അല്ലെങ്കിൽ ലഭിക്കുന്നതിന് അസിൻക്രണസ് പ്രവർത്തനങ്ങൾ ആവശ്യമുള്ള ഡാറ്റയുമായോ പ്രവർത്തിക്കുമ്പോൾ അസിങ്ക് ഇറ്ററേറ്ററുകൾ പ്രത്യേകിച്ചും ഉപയോഗപ്രദമാണ്.
അസിങ്ക് ഇറ്ററേറ്ററിൻ്റെ ഒരു അടിസ്ഥാന ഉദാഹരണം ഇതാ:
async function* generateNumbers() {
yield 1;
yield 2;
yield 3;
}
async function main() {
const iterator = generateNumbers();
let result = await iterator.next();
console.log(result); // { value: 1, done: false }
result = await iterator.next();
console.log(result); // { value: 2, done: false }
result = await iterator.next();
console.log(result); // { value: 3, done: false }
result = await iterator.next();
console.log(result); // { value: undefined, done: true }
}
main();
`scan` ഹെൽപ്പറിനെ പരിചയപ്പെടുത്തുന്നു
`scan` ഹെൽപ്പർ (അക്യുമുലേറ്റ് അല്ലെങ്കിൽ റിഡ്യൂസ് എന്നും അറിയപ്പെടുന്നു) ഓരോ മൂല്യത്തിനും ഒരു അക്യുമുലേറ്റർ ഫംഗ്ഷൻ പ്രയോഗിക്കുകയും സഞ്ചിത ഫലം പുറത്തുവിടുകയും ചെയ്തുകൊണ്ട് ഒരു അസിങ്ക് ഇറ്ററേറ്ററിനെ രൂപാന്തരപ്പെടുത്തുന്നു. ഇത് അറേകളിലെ `reduce` മെത്തേഡിന് സമാനമാണ്, പക്ഷേ അസിൻക്രണസ് ആയും ഇറ്ററേറ്ററുകളിലും പ്രവർത്തിക്കുന്നു.
ചുരുക്കത്തിൽ, `scan` ഒരു അസിങ്ക് ഇറ്ററേറ്റർ, ഒരു അക്യുമുലേറ്റർ ഫംഗ്ഷൻ, ഓപ്ഷണലായി ഒരു പ്രാരംഭ മൂല്യം എന്നിവ എടുക്കുന്നു. സോഴ്സ് ഇറ്ററേറ്റർ പുറത്തുവിടുന്ന ഓരോ മൂല്യത്തിനും, മുൻപ് ശേഖരിച്ച മൂല്യവും (അല്ലെങ്കിൽ ആദ്യത്തെ ആവർത്തനമാണെങ്കിൽ പ്രാരംഭ മൂല്യം) ഇറ്ററേറ്ററിൽ നിന്നുള്ള നിലവിലെ മൂല്യവും ഉപയോഗിച്ച് അക്യുമുലേറ്റർ ഫംഗ്ഷൻ വിളിക്കപ്പെടുന്നു. അക്യുമുലേറ്റർ ഫംഗ്ഷൻ്റെ ഫലം അടുത്ത സഞ്ചിത മൂല്യമായി മാറുന്നു, അത് പിന്നീട് തത്ഫലമായുണ്ടാകുന്ന അസിങ്ക് ഇറ്ററേറ്റർ പുറത്തുവിടുന്നു.
സിൻ്റാക്സും പാരാമീറ്ററുകളും
`scan` ഉപയോഗിക്കുന്നതിനുള്ള പൊതുവായ സിൻ്റാക്സ് താഴെ പറയുന്നവയാണ്:
async function* scan(sourceIterator, accumulator, initialValue) {
let accumulatedValue = initialValue;
for await (const value of sourceIterator) {
accumulatedValue = accumulator(accumulatedValue, value);
yield accumulatedValue;
}
}
- `sourceIterator`: രൂപാന്തരപ്പെടുത്തേണ്ട അസിങ്ക് ഇറ്ററേറ്റർ.
- `accumulator`: രണ്ട് ആർഗ്യുമെൻ്റുകൾ എടുക്കുന്ന ഒരു ഫംഗ്ഷൻ: മുമ്പത്തെ സഞ്ചിത മൂല്യവും ഇറ്ററേറ്ററിൽ നിന്നുള്ള നിലവിലെ മൂല്യവും. ഇത് പുതിയ സഞ്ചിത മൂല്യം നൽകണം.
- `initialValue` (ഓപ്ഷണൽ): അക്യുമുലേറ്ററിനുള്ള പ്രാരംഭ മൂല്യം. ഇത് നൽകിയിട്ടില്ലെങ്കിൽ, സോഴ്സ് ഇറ്ററേറ്ററിൽ നിന്നുള്ള ആദ്യത്തെ മൂല്യം പ്രാരംഭ മൂല്യമായി ഉപയോഗിക്കും, രണ്ടാമത്തെ മൂല്യം മുതൽ അക്യുമുലേറ്റർ ഫംഗ്ഷൻ വിളിക്കപ്പെടും.
ഉപയോഗങ്ങളും ഉദാഹരണങ്ങളും
`scan` ഹെൽപ്പർ അവിശ്വസനീയമാംവിധം വൈവിധ്യമാർന്നതും അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകൾ ഉൾപ്പെടുന്ന നിരവധി സാഹചര്യങ്ങളിൽ ഉപയോഗിക്കാവുന്നതുമാണ്. ചില ഉദാഹരണങ്ങൾ ഇതാ:
1. ഒരു റണ്ണിംഗ് ടോട്ടൽ കണക്കാക്കുന്നു
ഇടപാട് തുകകൾ പുറത്തുവിടുന്ന ഒരു അസിങ്ക് ഇറ്ററേറ്റർ നിങ്ങൾക്കുണ്ടെന്ന് കരുതുക. ഈ ഇടപാടുകളുടെ ഒരു റണ്ണിംഗ് ടോട്ടൽ കണക്കാക്കാൻ നിങ്ങൾക്ക് `scan` ഉപയോഗിക്കാം.
async function* generateTransactions() {
yield 10;
yield 20;
yield 30;
}
async function main() {
const transactions = generateTransactions();
const runningTotals = scan(transactions, (acc, value) => acc + value, 0);
for await (const total of runningTotals) {
console.log(total); // Output: 10, 30, 60
}
}
main();
ഈ ഉദാഹരണത്തിൽ, `accumulator` ഫംഗ്ഷൻ നിലവിലെ ഇടപാട് തുക മുമ്പത്തെ ടോട്ടലിലേക്ക് ചേർക്കുന്നു. `initialValue` 0 ആയി നൽകുന്നത് റണ്ണിംഗ് ടോട്ടൽ പൂജ്യത്തിൽ ആരംഭിക്കുന്നുവെന്ന് ഉറപ്പാക്കുന്നു.
2. ഡാറ്റ ഒരു അറേയിലേക്ക് ശേഖരിക്കുന്നു
ഒരു അസിങ്ക് ഇറ്ററേറ്ററിൽ നിന്ന് ഡാറ്റ ഒരു അറേയിലേക്ക് ശേഖരിക്കാൻ നിങ്ങൾക്ക് `scan` ഉപയോഗിക്കാം. കാലക്രമേണ ഡാറ്റ ശേഖരിക്കുന്നതിനും അത് ബാച്ചുകളായി പ്രോസസ്സ് ചെയ്യുന്നതിനും ഇത് ഉപയോഗപ്രദമാകും.
async function* fetchData() {
yield { id: 1, name: 'Alice' };
yield { id: 2, name: 'Bob' };
yield { id: 3, name: 'Charlie' };
}
async function main() {
const dataStream = fetchData();
const accumulatedData = scan(dataStream, (acc, value) => [...acc, value], []);
for await (const data of accumulatedData) {
console.log(data); // Output: [{id: 1, name: 'Alice'}], [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}], [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}, {id: 3, name: 'Charlie'}]
}
}
main();
ഇവിടെ, `accumulator` ഫംഗ്ഷൻ മുമ്പത്തെ എല്ലാ ഘടകങ്ങളും നിലവിലെ മൂല്യവും അടങ്ങുന്ന ഒരു പുതിയ അറേ ഉണ്ടാക്കാൻ സ്പ്രെഡ് ഓപ്പറേറ്റർ (`...`) ഉപയോഗിക്കുന്നു. `initialValue` ഒരു ശൂന്യമായ അറേയാണ്.
3. ഒരു റേറ്റ് ലിമിറ്റർ നടപ്പിലാക്കുന്നു
ഒരു റേറ്റ് ലിമിറ്റർ നടപ്പിലാക്കുക എന്നതാണ് കൂടുതൽ സങ്കീർണ്ണമായ ഉപയോഗം. ഒരു നിശ്ചിത സമയത്തിനുള്ളിൽ നടത്തിയ അഭ്യർത്ഥനകളുടെ എണ്ണം ട്രാക്ക് ചെയ്യാനും റേറ്റ് ലിമിറ്റ് കവിഞ്ഞാൽ തുടർന്നുള്ള അഭ്യർത്ഥനകൾ വൈകിപ്പിക്കാനും നിങ്ങൾക്ക് `scan` ഉപയോഗിക്കാം.
async function* generateRequests() {
// Simulate incoming requests
yield Date.now();
await new Promise(resolve => setTimeout(resolve, 200));
yield Date.now();
await new Promise(resolve => setTimeout(resolve, 100));
yield Date.now();
}
async function main() {
const requests = generateRequests();
const rateLimitWindow = 1000; // 1 second
const maxRequestsPerWindow = 2;
async function* rateLimitedRequests(source, window, maxRequests) {
let queue = [];
for await (const requestTime of source) {
queue.push(requestTime);
queue = queue.filter(t => requestTime - t < window);
if (queue.length > maxRequests) {
const earliestRequest = queue[0];
const delay = window - (requestTime - earliestRequest);
console.log(`Rate limit exceeded. Delaying for ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
yield requestTime;
}
}
const limited = rateLimitedRequests(requests, rateLimitWindow, maxRequestsPerWindow);
for await (const requestTime of limited) {
console.log(`Request processed at ${requestTime}`);
}
}
main();
ഈ ഉദാഹരണം അഭ്യർത്ഥന ടൈംസ്റ്റാമ്പുകളുടെ ഒരു ക്യൂ നിലനിർത്താൻ `scan` ആന്തരികമായി ( `rateLimitedRequests` ഫംഗ്ഷനിൽ) ഉപയോഗിക്കുന്നു. ഇത് റേറ്റ് ലിമിറ്റ് വിൻഡോയ്ക്കുള്ളിലെ അഭ്യർത്ഥനകളുടെ എണ്ണം അനുവദനീയമായ പരമാവധി കവിയുന്നുണ്ടോയെന്ന് പരിശോധിക്കുന്നു. അങ്ങനെയാണെങ്കിൽ, അത് ആവശ്യമായ കാലതാമസം കണക്കാക്കുകയും അഭ്യർത്ഥന നൽകുന്നതിന് മുമ്പ് താൽക്കാലികമായി നിർത്തുകയും ചെയ്യുന്നു.
4. ഒരു തത്സമയ ഡാറ്റാ അഗ്രഗേറ്റർ നിർമ്മിക്കുന്നു (ആഗോള ഉദാഹരണം)
വിവിധ എക്സ്ചേഞ്ചുകളിൽ നിന്ന് തത്സമയ സ്റ്റോക്ക് വിലകൾ സമാഹരിക്കേണ്ട ഒരു ആഗോള സാമ്പത്തിക ആപ്ലിക്കേഷൻ പരിഗണിക്കുക. ഒരു അസിങ്ക് ഇറ്ററേറ്ററിന് ന്യൂയോർക്ക് സ്റ്റോക്ക് എക്സ്ചേഞ്ച് (NYSE), ലണ്ടൻ സ്റ്റോക്ക് എക്സ്ചേഞ്ച് (LSE), ടോക്കിയോ സ്റ്റോക്ക് എക്സ്ചേഞ്ച് (TSE) പോലുള്ള എക്സ്ചേഞ്ചുകളിൽ നിന്ന് വില അപ്ഡേറ്റുകൾ സ്ട്രീം ചെയ്യാൻ കഴിയും. `scan` എല്ലാ എക്സ്ചേഞ്ചുകളിലുമുള്ള ഒരു പ്രത്യേക സ്റ്റോക്കിൻ്റെ റണ്ണിംഗ് ശരാശരി അല്ലെങ്കിൽ ഉയർന്ന/താഴ്ന്ന വില നിലനിർത്താൻ ഉപയോഗിക്കാം.
// Simulate streaming stock prices from different exchanges
async function* generateStockPrices() {
yield { exchange: 'NYSE', symbol: 'AAPL', price: 170.50 };
yield { exchange: 'LSE', symbol: 'AAPL', price: 170.75 };
await new Promise(resolve => setTimeout(resolve, 50));
yield { exchange: 'TSE', symbol: 'AAPL', price: 170.60 };
}
async function main() {
const stockPrices = generateStockPrices();
// Use scan to calculate a running average price
const runningAverages = scan(
stockPrices,
(acc, priceUpdate) => {
const { total, count } = acc;
return { total: total + priceUpdate.price, count: count + 1 };
},
{ total: 0, count: 0 }
);
for await (const averageData of runningAverages) {
const averagePrice = averageData.total / averageData.count;
console.log(`Running average price: ${averagePrice.toFixed(2)}`);
}
}
main();
ഈ ഉദാഹരണത്തിൽ, `accumulator` ഫംഗ്ഷൻ വിലകളുടെ റണ്ണിംഗ് ടോട്ടലും ലഭിച്ച അപ്ഡേറ്റുകളുടെ എണ്ണവും കണക്കാക്കുന്നു. ഈ സമാഹരിച്ച മൂല്യങ്ങളിൽ നിന്നാണ് അന്തിമ ശരാശരി വില കണക്കാക്കുന്നത്. ഇത് വിവിധ ആഗോള വിപണികളിലുടനീളമുള്ള സ്റ്റോക്ക് വിലയുടെ തത്സമയ കാഴ്ച നൽകുന്നു.
5. ആഗോളതലത്തിൽ വെബ്സൈറ്റ് ട്രാഫിക് വിശകലനം ചെയ്യുന്നു
ലോകമെമ്പാടുമുള്ള സെർവറുകളിൽ നിന്ന് വെബ്സൈറ്റ് സന്ദർശന ഡാറ്റയുടെ സ്ട്രീമുകൾ ലഭിക്കുന്ന ഒരു ആഗോള വെബ് അനലിറ്റിക്സ് പ്ലാറ്റ്ഫോം സങ്കൽപ്പിക്കുക. ഓരോ ഡാറ്റാ പോയിൻ്റും വെബ്സൈറ്റ് സന്ദർശിക്കുന്ന ഒരു ഉപയോക്താവിനെ പ്രതിനിധീകരിക്കുന്നു. `scan` ഉപയോഗിച്ച്, ഓരോ രാജ്യത്തിലെയും പേജ് വ്യൂകളുടെ ട്രെൻഡ് നമുക്ക് തത്സമയം വിശകലനം ചെയ്യാൻ കഴിയും. ഡാറ്റ ഇങ്ങനെയാണെന്ന് കരുതുക: `{ country: "US", page: "homepage", timestamp: 1678886400 }`.
async function* generateWebsiteVisits() {
yield { country: 'US', page: 'homepage', timestamp: Date.now() };
yield { country: 'CA', page: 'product', timestamp: Date.now() };
yield { country: 'UK', page: 'blog', timestamp: Date.now() };
yield { country: 'US', page: 'product', timestamp: Date.now() };
}
async function main() {
const visitStream = generateWebsiteVisits();
const pageViewCounts = scan(
visitStream,
(acc, visit) => {
const { country } = visit;
const newAcc = { ...acc };
newAcc[country] = (newAcc[country] || 0) + 1;
return newAcc;
},
{}
);
for await (const counts of pageViewCounts) {
console.log('Page view counts by country:', counts);
}
}
main();
ഇവിടെ, `accumulator` ഫംഗ്ഷൻ ഓരോ രാജ്യത്തിനുമുള്ള ഒരു കൗണ്ടർ അപ്ഡേറ്റ് ചെയ്യുന്നു. പുതിയ സന്ദർശന ഡാറ്റ എത്തുമ്പോൾ ഓരോ രാജ്യത്തിനുമുള്ള സഞ്ചിത പേജ് വ്യൂ കൗണ്ടുകൾ ഔട്ട്പുട്ടിൽ കാണിക്കും.
`scan` ഉപയോഗിക്കുന്നതിൻ്റെ പ്രയോജനങ്ങൾ
`scan` ഹെൽപ്പർ അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകളിൽ പ്രവർത്തിക്കുമ്പോൾ നിരവധി ഗുണങ്ങൾ വാഗ്ദാനം ചെയ്യുന്നു:
- ഡിക്ലറേറ്റീവ് ശൈലി: `scan` സഞ്ചിത പ്രോസസ്സിംഗ് ലോജിക് ഡിക്ലറേറ്റീവും സംക്ഷിപ്തവുമായ രീതിയിൽ പ്രകടിപ്പിക്കാൻ നിങ്ങളെ അനുവദിക്കുന്നു, ഇത് കോഡിൻ്റെ വായനാക്ഷമതയും പരിപാലനവും മെച്ചപ്പെടുത്തുന്നു.
- അസിൻക്രണസ് കൈകാര്യം ചെയ്യൽ: ഇത് അക്യുമുലേറ്റർ ഫംഗ്ഷനിലെ അസിൻക്രണസ് പ്രവർത്തനങ്ങളെ പരിധികളില്ലാതെ കൈകാര്യം ചെയ്യുന്നു, ഇത് I/O-ബൗണ്ട് ടാസ്ക്കുകൾ ഉൾപ്പെടുന്ന സങ്കീർണ്ണമായ സാഹചര്യങ്ങൾക്ക് അനുയോജ്യമാക്കുന്നു.
- തത്സമയ പ്രോസസ്സിംഗ്: `scan` ഡാറ്റാ സ്ട്രീമുകളുടെ തത്സമയ പ്രോസസ്സിംഗ് സാധ്യമാക്കുന്നു, മാറ്റങ്ങൾ സംഭവിക്കുമ്പോൾ പ്രതികരിക്കാൻ നിങ്ങളെ അനുവദിക്കുന്നു.
- സംയോജനക്ഷമത: സങ്കീർണ്ണമായ ഡാറ്റാ പ്രോസസ്സിംഗ് പൈപ്പ്ലൈനുകൾ സൃഷ്ടിക്കുന്നതിന് മറ്റ് അസിങ്ക് ഇറ്ററേറ്റർ ഹെൽപ്പറുകളുമായി ഇത് എളുപ്പത്തിൽ സംയോജിപ്പിക്കാൻ കഴിയും.
`scan` നടപ്പിലാക്കുന്നു (അത് ലഭ്യമല്ലെങ്കിൽ)
ചില ലൈബ്രറികൾ ഒരു ബിൽറ്റ്-ഇൻ `scan` ഹെൽപ്പർ നൽകുമ്പോൾ, ആവശ്യമെങ്കിൽ നിങ്ങൾക്ക് സ്വന്തമായി എളുപ്പത്തിൽ നടപ്പിലാക്കാൻ കഴിയും. ഒരു ലളിതമായ നിർവ്വഹണം ഇതാ:
async function* scan(sourceIterator, accumulator, initialValue) {
let accumulatedValue = initialValue;
let first = true;
for await (const value of sourceIterator) {
if (first && initialValue === undefined) {
accumulatedValue = value;
first = false;
} else {
accumulatedValue = accumulator(accumulatedValue, value);
}
yield accumulatedValue;
}
}
ഈ നിർവ്വഹണം സോഴ്സ് ഇറ്ററേറ്ററിലൂടെ ആവർത്തിക്കുകയും ഓരോ മൂല്യത്തിനും അക്യുമുലേറ്റർ ഫംഗ്ഷൻ പ്രയോഗിക്കുകയും ചെയ്യുന്നു, സഞ്ചിത ഫലം നൽകുന്നു. ഇത് `initialValue` നൽകാത്ത സന്ദർഭം സോഴ്സ് ഇറ്ററേറ്ററിൽ നിന്നുള്ള ആദ്യത്തെ മൂല്യം പ്രാരംഭ മൂല്യമായി ഉപയോഗിച്ച് കൈകാര്യം ചെയ്യുന്നു.
`reduce`-മായി താരതമ്യം
`scan`, `reduce` എന്നിവയെ വേർതിരിച്ചറിയേണ്ടത് പ്രധാനമാണ്. രണ്ടും ഇറ്ററേറ്ററുകളിൽ പ്രവർത്തിക്കുകയും ഒരു അക്യുമുലേറ്റർ ഫംഗ്ഷൻ ഉപയോഗിക്കുകയും ചെയ്യുമ്പോൾ, അവയുടെ സ്വഭാവത്തിലും ഔട്ട്പുട്ടിലും വ്യത്യാസമുണ്ട്.
- `scan` ഓരോ ആവർത്തനത്തിനും സഞ്ചിത മൂല്യം പുറത്തുവിടുന്നു, സമാഹരണത്തിൻ്റെ ഒരു റണ്ണിംഗ് ഹിസ്റ്ററി നൽകുന്നു.
- `reduce` ഇറ്ററേറ്ററിലെ എല്ലാ ഘടകങ്ങളും പ്രോസസ്സ് ചെയ്തതിന് ശേഷം അന്തിമ സഞ്ചിത മൂല്യം മാത്രം പുറത്തുവിടുന്നു.
അതിനാൽ, സമാഹരണത്തിൻ്റെ ഇടക്കാല അവസ്ഥകൾ ട്രാക്ക് ചെയ്യേണ്ട സാഹചര്യങ്ങൾക്ക് `scan` അനുയോജ്യമാണ്, അതേസമയം നിങ്ങൾക്ക് അന്തിമ ഫലം മാത്രം ആവശ്യമുള്ളപ്പോൾ `reduce` അനുയോജ്യമാണ്.
എറർ ഹാൻഡ്ലിംഗ്
അസിൻക്രണസ് ഇറ്ററേറ്ററുകളുമായും `scan` ആയും പ്രവർത്തിക്കുമ്പോൾ, പിശകുകൾ ഭംഗിയായി കൈകാര്യം ചെയ്യേണ്ടത് അത്യാവശ്യമാണ്. ആവർത്തന പ്രക്രിയയിലോ അക്യുമുലേറ്റർ ഫംഗ്ഷനിലോ പിശകുകൾ സംഭവിക്കാം. ഈ പിശകുകൾ പിടിക്കാനും കൈകാര്യം ചെയ്യാനും നിങ്ങൾക്ക് `try...catch` ബ്ലോക്കുകൾ ഉപയോഗിക്കാം.
async function* generatePotentiallyFailingData() {
yield 1;
yield 2;
throw new Error('Something went wrong!');
yield 3;
}
async function main() {
const dataStream = generatePotentiallyFailingData();
try {
const accumulatedData = scan(dataStream, (acc, value) => acc + value, 0);
for await (const data of accumulatedData) {
console.log(data);
}
} catch (error) {
console.error('An error occurred:', error);
}
}
main();
ഈ ഉദാഹരണത്തിൽ, `try...catch` ബ്ലോക്ക് `generatePotentiallyFailingData` ഇറ്ററേറ്റർ എറിയുന്ന പിശക് പിടിക്കുന്നു. തുടർന്ന് നിങ്ങൾക്ക് പിശക് ലോഗ് ചെയ്യുകയോ അല്ലെങ്കിൽ പ്രവർത്തനം വീണ്ടും ശ്രമിക്കുകയോ പോലുള്ള ഉചിതമായ രീതിയിൽ കൈകാര്യം ചെയ്യാൻ കഴിയും.
ഉപസംഹാരം
ജാവാസ്ക്രിപ്റ്റ് അസിങ്ക് ഇറ്ററേറ്ററുകളിൽ അസിൻക്രണസ് അക്യുമുലേറ്റീവ് പ്രോസസ്സിംഗ് നടത്തുന്നതിനുള്ള ഒരു ശക്തമായ ഉപകരണമാണ് `scan` ഹെൽപ്പർ. ഇത് സങ്കീർണ്ണമായ ഡാറ്റാ പരിവർത്തനങ്ങൾ ഡിക്ലറേറ്റീവും സംക്ഷിപ്തവുമായ രീതിയിൽ പ്രകടിപ്പിക്കാനും, അസിൻക്രണസ് പ്രവർത്തനങ്ങൾ ഭംഗിയായി കൈകാര്യം ചെയ്യാനും, ഡാറ്റാ സ്ട്രീമുകൾ തത്സമയം പ്രോസസ്സ് ചെയ്യാനും നിങ്ങളെ പ്രാപ്തരാക്കുന്നു. അതിൻ്റെ പ്രവർത്തനവും ഉപയോഗങ്ങളും മനസ്സിലാക്കുന്നതിലൂടെ, കൂടുതൽ കരുത്തുറ്റതും കാര്യക്ഷമവുമായ അസിൻക്രണസ് ആപ്ലിക്കേഷനുകൾ നിർമ്മിക്കാൻ നിങ്ങൾക്ക് `scan` പ്രയോജനപ്പെടുത്താം. നിങ്ങൾ റണ്ണിംഗ് ടോട്ടലുകൾ കണക്കാക്കുകയാണെങ്കിലും, ഡാറ്റ അറേകളിലേക്ക് ശേഖരിക്കുകയാണെങ്കിലും, റേറ്റ് ലിമിറ്ററുകൾ നടപ്പിലാക്കുകയാണെങ്കിലും, അല്ലെങ്കിൽ തത്സമയ ഡാറ്റാ അഗ്രഗേറ്ററുകൾ നിർമ്മിക്കുകയാണെങ്കിലും, `scan` നിങ്ങളുടെ കോഡ് ലളിതമാക്കുകയും അതിൻ്റെ മൊത്തത്തിലുള്ള പ്രകടനം മെച്ചപ്പെടുത്തുകയും ചെയ്യും. നിങ്ങളുടെ അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകൾ പ്രോസസ്സ് ചെയ്യുമ്പോൾ ഇടക്കാല സഞ്ചിത മൂല്യങ്ങളിലേക്ക് ആക്സസ്സ് ആവശ്യമുള്ളപ്പോൾ എറർ ഹാൻഡ്ലിംഗ് പരിഗണിക്കാനും `reduce`-ന് പകരം `scan` തിരഞ്ഞെടുക്കാനും ഓർമ്മിക്കുക. RxJS പോലുള്ള ലൈബ്രറികൾ പര്യവേക്ഷണം ചെയ്യുന്നത് റിയാക്ടീവ് പ്രോഗ്രാമിംഗ് മാതൃകകൾക്കുള്ളിൽ `scan`-നെക്കുറിച്ചുള്ള നിങ്ങളുടെ ധാരണയും പ്രായോഗിക പ്രയോഗവും കൂടുതൽ മെച്ചപ്പെടുത്തും.